package org.zsk.cfl.cmd;

import java.util.List;
import java.util.Map;

import org.flowable.bpmn.BpmnAutoLayout;
import org.flowable.bpmn.model.*;
import org.flowable.bpmn.model.Process;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.impl.cmd.AbstractDynamicInjectionCmd;
import org.flowable.engine.impl.context.Context;
import org.flowable.engine.impl.dynamic.BaseDynamicSubProcessInjectUtil;
import org.flowable.engine.impl.dynamic.DynamicUserTaskBuilder;
import org.flowable.engine.impl.persistence.entity.DeploymentEntity;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager;
import org.flowable.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.engine.impl.util.ProcessDefinitionUtil;

/**
 * <p>
 *     动态用户任务节点
 * </p>
 *
 * @author zsk
 * @date 2020/1/02 上午10:40
 */
public class SerialInjectUserTaskInProcessInstanceCmd extends AbstractDynamicInjectionCmd implements Command<Void> {

    protected String processInstanceId;
    protected String activityId;
    protected DynamicUserTaskBuilder dynamicUserTaskBuilder;

    public SerialInjectUserTaskInProcessInstanceCmd(String processInstanceId, DynamicUserTaskBuilder dynamicUserTaskBuilder, String activityId) {
        this.processInstanceId = processInstanceId;
        this.dynamicUserTaskBuilder = dynamicUserTaskBuilder;
        this.activityId=activityId;
    }

    @Override
    public Void execute(CommandContext commandContext) {
        createDerivedProcessDefinitionForProcessInstance(commandContext, processInstanceId);
        return null;
    }

    @Override
    protected void updateBpmnProcess(CommandContext commandContext, Process process,
                                     BpmnModel bpmnModel, ProcessDefinitionEntity originalProcessDefinitionEntity, DeploymentEntity newDeploymentEntity) {

        FlowNode chosenFlow=(FlowNode)process.getFlowElement(activityId);
        List<SequenceFlow> chosenOutgoings=chosenFlow.getOutgoingFlows();
        SequenceFlow chosenSeqFlow=chosenOutgoings.get(0);
        FlowNode chosenNextFlow=(FlowNode)process.getFlowElement(chosenSeqFlow.getTargetRef());
        process.removeFlowElement(chosenSeqFlow.getId());

        UserTask dynamicUserTask=new UserTask();
        if (dynamicUserTaskBuilder.getId() != null) {
            dynamicUserTask.setId(dynamicUserTaskBuilder.getId());
        } else {
            dynamicUserTask.setId(dynamicUserTaskBuilder.nextTaskId(process.getFlowElementMap()));
        }
        dynamicUserTaskBuilder.setDynamicTaskId(dynamicUserTask.getId());

        dynamicUserTask.setName(dynamicUserTaskBuilder.getName());
        dynamicUserTask.setAssignee(dynamicUserTaskBuilder.getAssignee());
        process.addFlowElement(dynamicUserTask);

        SequenceFlow flowToUserTask = new SequenceFlow(chosenFlow.getId(), dynamicUserTask.getId());
        flowToUserTask.setId(dynamicUserTaskBuilder.nextFlowId(process.getFlowElementMap()));
        process.addFlowElement(flowToUserTask);

        SequenceFlow flowFromUserTask = new SequenceFlow(dynamicUserTask.getId(), chosenNextFlow.getId());
        flowFromUserTask.setId(dynamicUserTaskBuilder.nextFlowId(process.getFlowElementMap()));
        process.addFlowElement(flowFromUserTask);

        flowToUserTask.setSourceRef(chosenFlow.getId());
        flowFromUserTask.setTargetRef(chosenNextFlow.getId());

        new BpmnAutoLayout(bpmnModel).execute();
//        GraphicInfo elementGraphicInfo = bpmnModel.getGraphicInfo(chosenFlow.getId());
//        if (elementGraphicInfo != null) {
//            double yDiff = 0;
//            double xDiff = 80;
//            if (elementGraphicInfo.getY() < 173) {
//                yDiff = 173 - elementGraphicInfo.getY();
//                elementGraphicInfo.setY(173);
//            }
//
//            Map<String, GraphicInfo> locationMap = bpmnModel.getLocationMap();
//            for (String locationId : locationMap.keySet()) {
//                if (chosenFlow.getId().equals(locationId)) {
//                    continue;
//                }
//
//                GraphicInfo locationGraphicInfo = locationMap.get(locationId);
//                locationGraphicInfo.setX(locationGraphicInfo.getX() + xDiff);
//                locationGraphicInfo.setY(locationGraphicInfo.getY() + yDiff);
//            }
//
//            Map<String, List<GraphicInfo>> flowLocationMap = bpmnModel.getFlowLocationMap();
//            for (String flowId : flowLocationMap.keySet()) {
//                if (flowToUserTask.getId().equals(flowId)) {
//                    continue;
//                }
//
//                List<GraphicInfo> flowGraphicInfoList = flowLocationMap.get(flowId);
//                for (GraphicInfo flowGraphicInfo : flowGraphicInfoList) {
//                    flowGraphicInfo.setX(flowGraphicInfo.getX() + xDiff);
//                    flowGraphicInfo.setY(flowGraphicInfo.getY() + yDiff);
//                }
//            }
//
//            GraphicInfo forkGraphicInfo = new GraphicInfo(elementGraphicInfo.getX() + 75, elementGraphicInfo.getY() - 5, 40, 40);
//            bpmnModel.addGraphicInfo(dynamicUserTask.getId(), forkGraphicInfo);
//
//            bpmnModel.addFlowGraphicInfoList(flowToUserTask.getId(), createWayPoints(elementGraphicInfo.getX() + 30, elementGraphicInfo.getY() + 15,
//                    elementGraphicInfo.getX() + 75, elementGraphicInfo.getY() + 15));
//
//            bpmnModel.addFlowGraphicInfoList(flowToUserTask.getId(), createWayPoints(elementGraphicInfo.getX() + 95, elementGraphicInfo.getY() - 5,
//                    elementGraphicInfo.getX() + 95, elementGraphicInfo.getY() - 123, elementGraphicInfo.getX() + 185, elementGraphicInfo.getY() - 123));
//
//            GraphicInfo endGraphicInfo = new GraphicInfo(elementGraphicInfo.getX() + 335, elementGraphicInfo.getY() - 137, 28, 28);
//            bpmnModel.addGraphicInfo(chosenNextFlow.getId(), endGraphicInfo);
//
//            bpmnModel.addFlowGraphicInfoList(flowFromUserTask.getId(), createWayPoints(elementGraphicInfo.getX() + 285, elementGraphicInfo.getY() - 123,
//                    elementGraphicInfo.getX() + 335, elementGraphicInfo.getY() - 123));
//        }

        BaseDynamicSubProcessInjectUtil.processFlowElements(commandContext, process, bpmnModel, originalProcessDefinitionEntity, newDeploymentEntity);
    }

    @Override
    protected void updateExecutions(CommandContext commandContext, ProcessDefinitionEntity processDefinitionEntity,
                                    ExecutionEntity processInstance, List<ExecutionEntity> childExecutions) {
    }

}